Routing & Accessibility
Development Impact (DIME)
April, 2024
This section will introduce calculating accessibility metrics in R. Specifically, we’ll work to understand questions such as:
Today, we’ll focus approaches using OpenStreetMaps. We’ll primarily rely on Open Source Routing Machine (OSRM) for determining accessibility, which is a routing engine that uses OpenStreetMap data.
Copy/paste the following code into a new RStudio script, replacing “YOURFOLDERPATHHERE” with the folder within which you’ll place this R project:
Install new packages
And load them
Load school data and convert to spatial object
Map two schools
Determine driving time between schools (measured in minutes)
Determine optimal route
drive_sf <- osrmRoute(src = schools_sf[1,],
dst = schools_sf[2,])
walk_sf <- osrmRoute(src = schools_sf[1,],
dst = schools_sf[2,],
osrm.profile = "foot")
leaflet() %>%
addTiles() %>%
addPolylines(data = drive_sf, opacity = 1, weight = 10) %>%
addPolylines(data = walk_sf, color = "orange", opacity = 1)Exercise:
Solution:
## School ids
id_1 <- 10
id_2 <- 20
## Route geometries
drive_sf <- osrmRoute(src = schools_sf[id_1,],
dst = schools_sf[id_2,])
walk_sf <- osrmRoute(src = schools_sf[id_1,],
dst = schools_sf[id_2,],
osrm.profile = "foot")
## Add travel time as a variable
drive_sf$travel_time <- osrmTable(src = schools_sf[id_1,],
dst = schools_sf[id_2,])$durations
walk_sf$travel_time <- osrmTable(src = schools_sf[id_1,],
dst = schools_sf[id_2,],
osrm.profile = "foot")$durations
print(c(drive_sf$travel_time, walk_sf$travel_time))[1] 5.9 41.2
Solution:
Compute travel time from the first school to the next 99 schools
Compute optimal routes:
osrmRoute only allows 1 O-D pair, so we apply over destinationsosrmRoute is slow, so we just look at 10 O-D pairsExercise: A student lives near school 1, but has options to go to all other schools. The student will have to walk to school and doesn’t want to cross a major road (trunk or motorway) to get to the school. How many schools can the student consider?
(To minimize computational time, only consider the first 20 schools).
Hint: Load the road files and subset to major roads. Which routes don’t intersect with a major road?
Solution:
iso_sf <- osrmIsochrone(
loc = schools_sf[1,],
breaks = seq(from = 0, to = 20, length.out = 5)
)
head(iso_sf)Simple feature collection with 4 features and 3 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 36.62947 ymin: -1.364402 xmax: 36.93593 ymax: -1.13673
Geodetic CRS: WGS 84
id isomin isomax geometry
1 1 0 5 MULTIPOLYGON (((36.784 -1.2...
2 2 5 10 MULTIPOLYGON (((36.84123 -1...
3 3 10 15 MULTIPOLYGON (((36.84123 -1...
4 4 15 20 MULTIPOLYGON (((36.81645 -1...
Exercise:
st_join to perform a spatial join).Simple feature collection with 6 features and 13 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: 36.67803 ymin: -1.370704 xmax: 36.99025 ymax: -1.234921
Geodetic CRS: WGS 84
# A tibble: 6 × 14
GID_2 GID_0 COUNTRY GID_1 NAME_1 NL_NAME_1 NAME_2 VARNAME_2 NL_NAME_2 TYPE_2
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 KEN.30… KEN Kenya KEN.… Nairo… <NA> Dagor… <NA> <NA> Const…
2 KEN.30… KEN Kenya KEN.… Nairo… <NA> Dagor… <NA> <NA> Const…
3 KEN.30… KEN Kenya KEN.… Nairo… <NA> Embak… <NA> <NA> Const…
4 KEN.30… KEN Kenya KEN.… Nairo… <NA> Embak… <NA> <NA> Const…
5 KEN.30… KEN Kenya KEN.… Nairo… <NA> Embak… <NA> <NA> Const…
6 KEN.30… KEN Kenya KEN.… Nairo… <NA> Embak… <NA> <NA> Const…
# ℹ 4 more variables: ENGTYPE_2 <chr>, CC_2 <chr>, HASC_2 <chr>,
# geometry <POLYGON [°]>
Solution:
Solution:
Instead of using Isochrones, we could also also determine the percent of schools within 10 minutes using osrmTable. One disadvatange of this approach is that the code can take longer to run; a separate query to OSRM is made for each school.
Isochrones show polygons that are reachable within a certain time. We can also compute an Isodistance, which shows polygons that are reachable within a certain driving distance.
iso_sf <- osrmIsodistance(
loc = schools_sf[1,],
breaks = c(2000, 4000, 6000, 8000, 10000) # meters
)
palette_1 <- colorNumeric(
palette = "viridis", domain = iso_sf$isomin
)
leaflet() %>%
addTiles() %>%
addCircles(data = schools_sf[1,], color = "red", opacity = 1) %>%
addPolygons(data = iso_sf,
fillColor = ~palette_1(isomin),
fillOpacity = 0.7,
stroke = F)The osrmIsochrone function only allows determining accessibility from one distance. In many cases were are interested in understanding accessibility to the closest location among many locations; for example, travel time to the nearest school.
Strategy:
The osrm package enables routing across a road network but does not consider live traffic conditions. We can leverage private sector data sources/APIs to query travel time between origin and destinations that incorporate traffic conditions.
Google:
gmapsdistance package facilitates using the API. The gmapsdistance function works similarly to the osrmTable function:Mapbox:
mapboxapi package facilitates using the API. The mb_matrix function works similarly to osrmTable function:We may also be interested in routing based on scenarios that we define. For example, by changing the speed limit of a road, removing a road, adding a road, etc. This task can be more complicated and there are multiple approaches:
Routing using a graph
Resources for this approach:
Routing using a gridded approach
One disadvantage with the above approach is that converting the road network spatial file into a graph can be cumbersome. Another approach that can be more straightforward but assumes some simplifcation of the road network:
Resources for this approach: